
function decodeOcTree(fusedPointcloud_source, arrUnit8) {
    console.log("开始解压");
    // if (!fusedPointcloud_source) return;
    //获取压缩的unit8Array
    // let fusedPointcloud_data_asu8 = fusedPointcloud_source.getData_asU8(); //这是压缩数据；格式是unit8Arrty
    let fusedPointcloud_data_asu8 = arrUnit8; //这是压缩数据；格式是unit8Arrty
    const dataView = new DataView(fusedPointcloud_data_asu8.buffer);
    // fusedPointcloud_source = null;
    //提取octree的长度；
    let octreeLen = Number(dataView.getBigUint64());

    // 解压octree数据;
    // let xyzListUnit = fusedPointcloud_data_asu8.slice(8, octreeLen + 8);
    let xyzList = getOctreeXYZ(dataView, 8);

    //解压flag
    let flagLen = Number(dataView.getBigUint64(octreeLen + 8));
    let flagList = getFlagList(dataView, octreeLen + 16, flagLen);
    console.log(`解压结束:点-${xyzList.length}`);
    return {
        xyzList,        
        flagList
    };
}



/**
 * 解压octree数据
 * @param {*} data 原始加密串
 * @param {*} start  从8个字节位开始；（前八个 是octree的长度)
 * @param {*} end 
 * @returns 
 */
function getOctreeXYZ(dataView, offset) {
    //前24个字节；解压最大值 最小值
    let maxminRoot = getMaxMinRoot(dataView, offset);
    //解压 depth
    let depth = Number(dataView.getBigInt64(offset + 24))//getLenNum(data.slice(24, 32))
    //存储xyz点
    let pointList = []
    offset = deserialize(depth, pointList, dataView, offset + 32, maxminRoot);
    return pointList
}
/**
 * 
 * @param {*} depth 
 * @param {*} tree 节点：maxminObj 存放min max； name：存放unit8，children
 * @param {function} getItem  从octree加密串中获取unit8；并构造tree node 节点
 * @param {*} list  存放叶子节点，并计算center；
 * @returns 
 */
function deserialize(depth, pointList, dataView, offset, maxmin) {
    if (depth == 0) {
        let pointMid = {
            x: (maxmin.max.x + maxmin.min.x) / 2,
            y: (maxmin.max.y + maxmin.min.y) / 2,
            z: (maxmin.max.z + maxmin.min.z) / 2
        }
        pointList.push(pointMid);
    } else {
        const idx = dataView.getUint8(offset);
        offset++;
        for (let i = 0; i < 8; i++) {
            if (idx & (1 << i)) {
                let maxmin_child = getMinMax(i, maxmin);
                offset = deserialize(depth - 1, pointList, dataView, offset, maxmin_child);
            }
        }
    }
    return offset;
}

module.exports = {
    decodeOcTree
}

/**
 * 解压root的min max
 * @param {*} dataView 
 * @param {*} offset 
 * @returns 
 */
function getMaxMinRoot(dataView, offset) {
    let arr = []
    for (let i = 0; i < 6; i++) {
        arr.push(dataView.getFloat32(offset + i * 4))
    }
    return {
        min: {
            x: arr[0],
            y: arr[1],
            z: arr[2]
        },
        max: {
            x: arr[3],
            y: arr[4],
            z: arr[5]
        }
    }
}
/**
 * 获取当前节点的min max
 * @param {*} index 0-7 哪个块
 * @param {*} min  父节点的min
 * @param {*} max  父节点的max
 * @returns 
 */
function getMinMax(index, minmax) {
    let { min, max } = minmax;
    let result = {
        min: {},
        max: {}
    }
    let mid = {
        x: (min.x + max.x) / 2,
        y: (min.y + max.y) / 2,
        z: (min.z + max.z) / 2
    }
    if (index & 4) {
        result.min.x = min.x;
        result.max.x = mid.x;
    } else {
        result.min.x = mid.x;
        result.max.x = max.x;
    }
    if (index & 2) {
        result.min.y = min.y;
        result.max.y = mid.y;
    } else {
        result.min.y = mid.y;
        result.max.y = max.y;
    }
    if (index & 1) {
        result.min.z = min.z;
        result.max.z = mid.z;
    } else {
        result.min.z = mid.z;
        result.max.z = max.z;
    }
    return result;
}

function getFlagList(dataView, offset, len) {
    let flagResult = []
    for (let i = 0; i < len; i++) {
        let val = dataView.getUint8(offset + i);
        for (let m = 7; m >= 0; m--) {
            let flag = {
                movable: 0,
                ground: false,
            }
            if (val & (1 << m)) {
                m--;
                if (val & (1 << m)) {
                    //11
                    flag.ground = true
                } else {
                    //10
                    flag.movable = 2;
                }
            } else {
                m--;
                if (val & (1 << m)) {
                    //01
                    flag.movable = 1;
                } else {
                    //00
                    flag.movable = 0;
                }
            }
            flagResult.push(flag);
        }
    }
    return flagResult
}
